package cn.tedu.charging.device.service.impl;

import cn.tedu.charging.common.pojo.po.ChargingGunInfoPO;
import cn.tedu.charging.common.pojo.po.ChargingStationPO;
import cn.tedu.charging.common.pojo.query.NearStationsQuery;
import cn.tedu.charging.common.pojo.vo.GunInfoVO;
import cn.tedu.charging.common.pojo.vo.StationDetailVO;
import cn.tedu.charging.common.pojo.vo.StationInfoVO;
import cn.tedu.charging.device.repository.DeviceRepository;
import cn.tedu.charging.device.service.DeviceService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.Distance;
import org.springframework.data.geo.GeoResult;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class DeviceServiceImpl implements DeviceService {
    @Autowired
    private DeviceRepository deviceRepository;
    @Override
    public List<StationInfoVO> nearStations(NearStationsQuery query) {
        //stationInfoVO list是什么特点
        /*
        1.geo中圆查询命中的元素有几个 返回voLiSt就有几个
        2.只读取redis的数据,只能封装vo对象部分属性(stationId lng lat distance) (stationName status)*/
        //第一步 调用仓储层 查询命中geo集合
        List<GeoResult> stationGeos = deviceRepository.nearStations(query);
        //判断在非空的时候 组织映射 返回vo列表
        List<StationInfoVO> vos=null;
        if (stationGeos!=null&&stationGeos.size()>0){
            vos=stationGeos.stream().map(geo->{
                //映射计算 GeoResult 解析数据 补充属性 组织vo返回
                return parseGeo2Vo(geo);
            }).collect(Collectors.toList());
        }
        return vos;
    }

    private StationInfoVO parseGeo2Vo(GeoResult geo) {
        StationInfoVO vo=new StationInfoVO();
        //1.distance
        double distance = geo.getDistance().getValue();//821.75m
        //对浮点数 取2位小数 第三位以后 四舍五入0.82km
        distance=new BigDecimal(distance+"").divide(new BigDecimal("1000")).setScale(2, RoundingMode.HALF_UP).doubleValue();
        vo.setDistance(distance);
        //2.point lng lat
        RedisGeoCommands.GeoLocation<Integer> location=(RedisGeoCommands.GeoLocation<Integer>)geo.getContent();//RedisGeoCommands.GeoLocation
        Point point = location.getPoint();
        vo.setStationLng(new BigDecimal(point.getX()+""));
        vo.setStationLat(new BigDecimal(point.getY()+""));
        //3.stationId geoResult元素值
        Integer stationId = location.getName();
        vo.setStationId(stationId);
        //4.avgPrice 模拟假的数据
        vo.setAvgPrice(1.27);
        //5.stationName stationStatus 调用仓储层利用stationId查询stationPO
        ChargingStationPO stationPO = deviceRepository.getStationById(stationId);
        vo.setStationName(stationPO.getStationName());
        vo.setStationStatus(stationPO.getStationStatus());
        return vo;
    }

    @Override
    public StationDetailVO detailStation(Integer stationId) {
        //1.调用数据入口 根据id查询场站
        ChargingStationPO stationPO = deviceRepository.getStationById(stationId);
        //判断非空
        StationDetailVO vo=new StationDetailVO();
        if (stationPO!=null){
            log.info("查到场站数据");
            //2.stationPO具备 stationName address 使用stationId条件查询场站下的所有枪 TODO
            List<ChargingGunInfoPO> gunInfoPOS = deviceRepository.getGunListByStationId(stationId);
            //3.gunInfoPos可以用来封装转化gunInfoVOs
            vo.setAddress(stationPO.getAddress());
            vo.setStationName(stationPO.getStationName());
            //在查询到该场站下的所有枪之后 才转化封装
            if (gunInfoPOS!=null&& gunInfoPOS.size()>0){
                //list stream()
                vo.setGunInfoVos(gunInfoPOS.stream().map(po->{
                    GunInfoVO gunInfoVO=new GunInfoVO();
                    gunInfoVO.setGunId(po.getId());
                    BeanUtils.copyProperties(po,gunInfoVO);
                    return gunInfoVO;
                }).collect(Collectors.toList()));
            }
        }
        return vo;
    }
    //TODO
    @Override
    public Object updateGunStatus(Integer gunId, Integer status) {
        return null;
    }
}
